home *** CD-ROM | disk | FTP | other *** search
-
- Hi!
-
- Here is the wrapped sprite code, as advertised. It is *far* from optimal,
- since I had only one wrapped sprite to worry about in the demo it was
- written for.
-
- It will almost certainly need work to assemble, since it has been taken
- from a larger game. If you get *really* stuck, I'm happy to answer e-mail.
-
- It consits of "GLOBALS.INC", "STRUCTS.INC", "VGA.INC", "SPRITES.ASM"
-
- ********* Cut Here for Globals.INC ------------------------------------------
- ;----------------------------------------------------------------------------:
- ; GLOBALS.INC :
- ; :
- ;----------------------------------------------------------------------------:
-
- ;----------------------------------------------------------------------------:
- ; DATA SEGMENT :
- ;----------------------------------------------------------------------------:
-
-
- SEGMENT Data_Segment DWORD PUBLIC USE32 'DATA'
- ENDS Data_Segment
-
- ;----------------------------------------------------------------------------:
- ; CODE SEGMENT :
- ;----------------------------------------------------------------------------:
-
-
- SEGMENT Code_Segment DWORD PUBLIC USE16 'CODE'
- ENDS Code_Segment
-
- ;----------------------------------------------------------------------------:
- ; VIDEO SEGMENT :
- ;----------------------------------------------------------------------------:
-
- SEGMENT Video_Segment AT 0a000h
- ENDS Video_Segment
-
-
- ;----------------------------------------------------------------------------:
- ; VGA Globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL Test_Card:NEAR,Unchain:NEAR,Set_VGA_Colour:NEAR
- GLOBAL Enable_VGA_Bit_Plane:NEAR,Copy_Screen_to_VGA:NEAR
-
-
- ;----------------------------------------------------------------------------:
- ; file globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL Get_File:NEAR,File_Data:BYTE:0fff0h,File_Name_List:WORD
-
-
- ;----------------------------------------------------------------------------:
- ; Fatal error globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL Fuckup:FAR
-
- ;----------------------------------------------------------------------------:
- ; Sprite Globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL Display_Unclipped_Sprite:NEAR,Erase_Unclipped_Sprite:NEAR
- GLOBAL Display_Clipped_Sprite:NEAR,Display_Wrapped_Sprite:NEAR
- GLOBAL Save_Unclipped_Background:NEAR,Display_Unclipped_Block:NEAR
- GLOBAL Limit_Sprite:NEAR
- GLOBAL Set_Up_Frame:NEAR,Separate_Sprite_Planes:NEAR
- GLOBAL Separate_Mask_Planes:NEAR
- GLOBAL Set_Up_Sprite:NEAR,Reset_Sprite_Data:NEAR
- GLOBAL Image_Buffer:BYTE:64000
- GLOBAL Display_Wrapped_Mask:NEAR
-
- Sprite_Item_Size = 32
- Frame_Item_Size = 16
-
- ;----------------------------------------------------------------------------:
- ; VBlank Globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL VBlank_Service:FAR
- GLOBAL Screen_Buffer:BYTE:64000
-
- ;----------------------------------------------------------------------------:
- ; Scroll Globals :
- ;----------------------------------------------------------------------------:
-
- GLOBAL Scroll_Left:NEAR,Scroll_Right:NEAR
-
-
- ;----------------------------------------------------------------------------:
- ; Symbols for frames of animation :
- ;----------------------------------------------------------------------------:
-
- Maximum_Sprites = 32
- Maximum_Frames = 100
- Maximum_Files = Maximum_Frames
-
- ;----------------------------------------------------------------------------:
- ; Error numbers :
- ;----------------------------------------------------------------------------:
-
- File_Fuckup EQU 0
- Image_Space_Fuckup EQU 1
-
- ****** Cut here for "STRUCTS.INC" ---------------------------------------------
- ;----------------------------------------------------------------------------:
- ; STRUCTS.INC :
- ; :
- ;----------------------------------------------------------------------------:
-
-
- ;----------------------------------------------------------------------------:
- ; States of sprite :
- ;----------------------------------------------------------------------------:
-
- Sprite_Flipped_X EQU 128
- Sprite_Flipped_Y EQU 64
- Sprite_Clipped_X EQU 32
- Sprite_Clipped_Y EQU 16
- Sprite_Enabled EQU 1
-
- ;----------------------------------------------------------------------------:
- ; An item in the Sprite List :
- ;----------------------------------------------------------------------------:
- Sprite_Swap_Size EQU 11 ; 11 bytes to swap on switch
-
- STRUC Sprite_Item
-
- Current_X dw 0 ; position of sprite on
- Current_Y dw 0 ; logical screen
- Current_Frame dw 0 ; frame in animation frame list
- Current_Background dw 0ffffh ; pointer to saved background
- Current_Address dw 0 ; pointer to address in vidram
- Current_Left_Plane db 0 ; side of sprite
-
- Padding db 0 ; let's keep it word aligned
-
- Previous_X dw 0 ; host address of top left
- Previous_Y dw 0 ; corner of sprite
- Previous_Frame dw 0
- Previous_Background dw 0ffffh
- Previous_Address dw 0
- Previous_Left_Plane db 0 ; pointer to plane of left hand
-
- Inertia dw 0
-
- X_Velocity db 0
- Y_Velocity db 0
-
- Sprite_State db 0 ; state of sprite (flipped, clipped)
- dw 0
- dw 0
-
-
- ENDS Sprite_Item
-
-
- GLOBAL Sprite_List:Sprite_Item:Maximum_Sprites
-
-
- ;----------------------------------------------------------------------------:
- ; A frame of animation in the animation list :
- ;----------------------------------------------------------------------------:
-
- STRUC Frame_Item
-
- Image_Data dd ? ; address of image of frame
- Image_X_Size dw ? ; x and y dimensions
- Image_Y_Size dw ?
- Image_Mask dd ? ; address of count mask
- Image_Data_Size dw ? ; size of all image data
- Image_Plane_Size dw ? ; size of 1 planes data in bytes
-
- ENDS Frame_Item
-
-
- GLOBAL Frame_List:Frame_Item:Maximum_Frames
-
- ;----------------------------------------------------------------------------:
- ; The header of a .PCX or .PCC file :
- ;----------------------------------------------------------------------------:
-
- STRUC PCX_Header
- Id db ?
- Version db ?
- Encoding_Mode db ?
- Bits_per_Pixel db ?
- X1 dw ?
- Y1 dw ?
- X2 dw ?
- Y2 dw ?
- Horizontal_Resolution dw ?
- Vertical_Resolution dw ?
- Colour_Map db 48 dup (?)
- Not_Used db ?
- Number_Of_Planes db ?
- Bits_per_Plane_Line dw ?
- Palette_Information dw ?
- dw ?
- dw ?
- Extra db 54 dup (?)
- ENDS PCX_Header
-
- ;----------------------------------------------------------------------------:
- ; A Colour Look up Table, or Palette! :
- ;----------------------------------------------------------------------------:
-
-
- STRUC PCX_CLUT
- Colour_Information db 3 dup (256 dup (?))
- ENDS PCX_CLUT
-
-
- ********* Cut here for "VGA.INC"-----------------------------------------------
- ;----------------------------------------------------------------------------:
- ; :
- ; INCLUDE File for VGA constants and useful macros :
- ;----------------------------------------------------------------------------:
-
-
- ;----------------------------------------------------------------------------:
- ; Colour VGA register equates :
- ;----------------------------------------------------------------------------:
-
-
- ; I/O ports for accessing VGA
-
- Miscellaneous_Output_Write_Port EQU 03c2h
- Miscellaneous_Output_Read_Port EQU 03cch
- Input_Status_0_Port EQU 03c2h
- Input_Status_1_Port EQU 03dah
- Sequencer_Address_Port EQU 03c4h
- Sequencer_Data_Port EQU 03c5h
- CRTC_Address_Port EQU 03d4h
- CRTC_Data_Port EQU 03d5h
- Graphics_Address_Port EQU 03ceh
- Graphics_Data_Port EQU 03cfh
- Attribute_Address_Write_Port EQU 03c0h
- Attribute_Address_Read_Port EQU 03c1h
- PEL_Address_Write_Mode_Port EQU 03c8h
- PEL_Address_Read_Mode_Port EQU 03c7h
- PEL_Data_Port EQU 03c9h
- DAC_State_Port EQU 03c7h
- PEL_Mask_Port EQU 03c6h
-
-
- ; Addresses of sequencer registers
-
- Reset EQU 0
- Clocking_Mode EQU 1
- Map_Mask EQU 2
- Character_Map_Select EQU 3
- Memory_Mode EQU 4
-
- ; Addresses of CRTC registers
-
- Horizontal_Total EQU 0
- Horizontal_Display_End EQU 1
- Start_Horizontal_Blanking EQU 2
- End_Horizontal_Blanking EQU 3
- Start_Horizontal_Retrace EQU 4
- End_Horizontal_Retrace EQU 5
- Vertical_Total EQU 6
- Overflow EQU 7
- Preset_Row_Scan EQU 8
- Max_Scan_Line EQU 9
- Cursor_Start EQU 10
- Cursor_End EQU 11
- Start_Address_High EQU 12
- Start_Address_Low EQU 13
- Cursor_Location_High EQU 14
- Cursor_Location_Low EQU 15
- Vertical_Retrace_Start EQU 16
- Vertical_Retrace_End EQU 17
- Vertical_Display_End EQU 18
- ;Offset EQU 19 ; ATCHUNG!! Name Conflict.
- Underline_Location EQU 20
- Start_Vertical_Blanking EQU 21
- End_Vertical_Blanking EQU 22
- Mode_Control EQU 23
- Line_Compare EQU 24
-
- ; Addresses of Graphics registers
-
- Set_Reset EQU 0
- Enable_Set_Reset EQU 1
- Colour_Compare EQU 2
- Data_Rotate EQU 3
- Read_Map_Select EQU 4
- Mode EQU 5
- Miscellaneous EQU 6
- Colour_Dont_Care EQU 7
- Bit_Mask EQU 8
-
- ; Addresses of Attribute registers
-
- Palette EQU 0
- Attribute_Mode_Control EQU 010h
- Overscan_Colour EQU 011h
- Colour_Plane_Enable EQU 012h
- Horizontal_Pixel_Panning EQU 013h
- Colour_Select EQU 014h
-
- MACRO Wait_for_Vertical_Retrace
- LOCAL VR_Wait
- PUSH AX
- PUSH DX
- VR_Wait:
- MOV DX,Input_Status_1_Port ; hang around for vblank tick
- IN AL,DX
- TEST AL,8
- JZ SHORT VR_Wait
- POP DX
- POP AX
- ENDM
-
- ;----------------------------------------------------------------------------:
- ; Screen Resolution :
- ;----------------------------------------------------------------------------:
-
- VGA_X_Resolution EQU 320
- VGA_Y_Resolution EQU 200
-
- ************** Cut here for SPRITES.ASM --------------------------------------
- ;----------------------------------------------------------------------------:
- ; Sprites.ASM :
- ; (C) John Connors 1993 :
- ;----------------------------------------------------------------------------:
-
- IDEAL
- P386N
-
- INCLUDE "GLOBALS.INC"
- INCLUDE "STRUCTS.INC"
- INCLUDE "VGA.INC"
-
-
- ;-----------------------------------------------------------------------------:
- ; MACROS :
- ;-----------------------------------------------------------------------------:
-
- ;----------------------------------------------------------------------------:
- ; With X in BX and y in CX compute video address, into EDI, mask into AL :
- ; CX, BX preserved EDI, AH destroyed. :
- ; * This computes the video address on the currently nondisplayed screen :
- ;----------------------------------------------------------------------------:
-
- ; Logical_Scan_Start_Address holds the offset of the page to plot
- ; the sprite on.. it will be undefined when you assemble.
- ; You need to change it to whatever *your* double buffering code
- ; uses.
-
- MACRO Compute_Video_Address
- ADD BX,[SMALL Left_Hand_Bit_Plane]
- MOV AX,CX ; width of display in bytes
- SHL AX,4
- MOV CX,AX
- SHL AX,2
- ADD AX,CX ; multiplied by y
- MOV CX,BX ; duplicate x for mask
- SHR BX,2 ; shift out bits used for mask
- MOV DI,[SMALL WORD PTR Logical_Scan_Start_Address]
- ADD DI,AX ; add x and y contributions
- ADD DI,BX
- MOV AL,CL ; AL is low bits of X
- AND AX,3 ; mask is bottom two bits
- ENDM
-
- ;----------------------------------------------------------------------------:
- ; DATA SEGMENT :
- ;----------------------------------------------------------------------------:
-
-
- SEGMENT Data_Segment DWORD PUBLIC USE32 'DATA'
- INCLUDE "DATA.INC"
-
- ALIGN 4
-
- ;----------------------------------------------------------------------------:
- ; buffer to hold sprite image data :
- ;----------------------------------------------------------------------------:
-
- Bottom_of_Image_Buffer dd 0
-
- ;----------------------------------------------------------------------------:
- ; list of sprites :
- ;----------------------------------------------------------------------------:
-
- ALIGN 4
-
- Sprite_List Sprite_Item Maximum_Sprites DUP (<>)
- Sprite_Item_Size = SIZE Sprite_List
-
- ;----------------------------------------------------------------------------:
- ; list of frames for animation :
- ;----------------------------------------------------------------------------:
-
- ALIGN 4
-
- Frame_List Frame_Item Maximum_Frames DUP (<>)
- Frame_Item_Size = SIZE Frame_List
-
-
- Map_Mask_Lookup db 01,02,04,08 ; translate plane # into mask
-
- ENDS Data_Segment
-
- ;----------------------------------------------------------------------------:
- ; IMAGE SEGMENT (Segment to hold image data for sprite frames :
- ;----------------------------------------------------------------------------:
-
- SEGMENT Image_Segment PARA PUBLIC USE32 'DATA'
-
- ALIGN 4
-
- Image_Buffer db 64000 dup (?) ; a lot of bytes!
- db 64000 dup (?)
-
- ENDS Image_Segment
-
- ;----------------------------------------------------------------------------:
- ; Transfer image data of sprites current frame to screen :
- ; Performs X wrapping only :
- ; Sprite colour 0 is treated as transparent :
- ; Enter with sprite number to display in EAX :
- ; :
- ; This code is part of a larger game and I have not time to re-write it so :
- ; that it works with normal mode x sprites :
- ; EAX is an index into the Sprite list, which holds X Y co-ords of sprites :
- ; and things like that. The sprite list also contains an index into the :
- ; Image list which holds the raw binary data for sprite images :
- ; The Image is read from a .PCX file and laid out plane by plane :
- ; :
- ; Plane #1 Row #1, Row #2, Row #3... :
- ; Plane #2 Row #1, Row #2, Row #3... :
- ; :
- ; The planes of the image are assumed all to be the size of the largest plane:
- ; in the image (so if only plane one has an extra pixel, the others will :
- ; be padded out) :
- ; :
- ; The code is also far from optimal. For a start neither source or :
- ; or destination of the image transfer to VGA ram is word aligned :
- ; .. and they *pay* me for this..sheesh! :
- ;----------------------------------------------------------------------------:
-
- PROC Display_Wrapped_Sprite NEAR
- LOCAL Wrapped_Width:WORD,UnWrapped_Width:WORD
- LOCAL Wrap_Flag:BYTE,X_Pixel:WORD,Plane_Size:WORD
- LOCAL Source_Plane:BYTE,Sprite_State:BYTE
- LOCAL Plane_Number:WORD,Plane_Width:WORD
- LOCAL Image_Width:WORD,Image_Height:WORD,Destination_Start:WORD
- LOCAL Source_Start:WORD =Local_Length
-
- ENTER Local_Length,0
-
- PUSHAD ; save registers
- PUSH DS
-
- ASSUME DS:Data_Segment
-
- MOV DX,Video_Segment
- MOV ES,DX ; ES points to VGA's segment
- ASSUME ES:Video_Segment
-
- ERRIF (Sprite_Item_Size NE 20h) ; form address of sprite in SI
- MOV SI,AX
- SHL SI,5
- ADD SI,OFFSET Sprite_List
- ; get state of sprite
- MOV AL,[(Sprite_Item PTR SI).Sprite_State]
- MOV [Sprite_State],AL
- ; get sprite x y
- MOV BX,[(Sprite_Item PTR SI).Current_X]
- MOV CX,[(Sprite_Item PTR SI).Current_Y]
- MOV [X_Pixel],BX ; save for x wrapping
- CMP BX,VGA_X_Resolution ; trivially reject (off right)
- JGE NEAR @@Done_Last_Pixel
- Compute_Video_Address
- MOV [Destination_Start],DI ; video address
- MOV [Plane_Number],AX ; first screen plane of sprite
- ; form frame address in DI
- MOV DI,[(Sprite_Item PTR SI).Current_Frame]
- SHL DI,4
- ADD DI,OFFSET Frame_List
- MOV AX,[(Frame_Item PTR DI).Image_Plane_Size]
- MOV [Plane_Size],AX
- ; get sprite dimensions etc.
- MOV BX,[(Frame_Item PTR DI).Image_X_Size]
- MOV [Image_Width],BX
- MOV AX,BX ; get image width in acc
- ADD AX,[X_Pixel]
- CMP AX,VGA_X_Resolution
- SETGE [Wrap_Flag] ; do we need to wrap?
- MOV AX,BX ; work out absolute width of
- AND AX,NOT 3 ; a source plane (width of
- CMP AX,BX ; widest plane in source)
- JZ SHORT @@No_Plane_Adjust
- ADD AX,4
- @@No_Plane_Adjust:
- SHR AX,2
- MOV [Plane_Width],AX
- MOV CX,[(Frame_Item PTR DI).Image_Y_Size]
- MOV [Image_Height],CX
- ; get address of sprite image
- MOV ESI,[(Frame_Item PTR DI).Image_Data]
- MOV [Source_Start],SI ; SI is smallest possible offset
-
- SHR ESI,16
- MOV AX,SI ; get address to get image from
- MOV DS,AX ; in DS:SI (sauce)
- ASSUME DS:NOTHING ; where?
-
- MOV CX,4 ; four planes
- @@Next_Plane:
- PUSH CX
- ; for each plane
- ; set VGA write plane
- MOV SI,[Plane_Number]
- MOV AH,[BYTE CS:@@Map_Mask_Lookup+SI]
- MOV AL,Map_Mask
- MOV DX,Sequencer_Address_Port
- OUT DX,AX
-
- ; work out physical plane width (ie width of plane as actually
- ; displayed without padding)
-
- MOV BX,[Image_Width]
- ADD BX,CX
- DEC BX ; cx is plane count
- SHR BX,2 ; bx is now plane width
- MOV [UnWrapped_Width],BX ; assume no wrapping
- MOV AL,[Wrap_Flag]
- OR AL,AL ; check for wrapping?
- JZ SHORT @@Wrapping_Done
- @@X_Wrap:
- MOV AX,[UnWrapped_Width] ; yes, we have to adjust
- MOV BX,VGA_X_Resolution-1 ; sprite width
- SUB BX,[X_Pixel]
- SHR BX,2
- INC BX
- MOV [UnWrapped_Width],BX ; this is the new width
- SUB AX,BX
- MOV [Wrapped_Width],AX ; this is the width of
- ; the bit on the other side
- ; of the screen
- @@Wrapping_Done:
- MOV CX,[Image_Height]
- MOVZX ESI,[Source_Start]
- @@No_Source_Adjust:
- MOV DI,[Destination_Start]
- MOV DX,320/4 ; screen row length
- @@Next_Row:
- ; for each row
- PUSH CX
- PUSH DI
- PUSH SI
- MOV BX,2
-
- MOV CX,[UnWrapped_Width]
- SHR CX,1
- JZ SHORT @@Words_Done
-
- ALIGN 4 ; optimise loop jump
- @@Next_Word:
- LODSW
- OR AX,AX
- JZ SHORT @@Transparent_Word ; most pixels in my
- ; sprites are transparent
- ; so I check for this first
- OR AL,AL
- JZ SHORT @@Transparent0
- MOV [ES:DI],AL
- @@Transparent0:
- OR AH,AH
- JZ SHORT @@Transparent1
- MOV [ES:DI+1],AH
- @@Transparent1:
- @@Transparent_Word:
- ADD DI,BX
- LOOP SHORT @@Next_Word
- @@Words_Done:
- MOV CX,[UnWrapped_Width]
- RCR CX,1
- JNC SHORT @@Do_Wrapped_Side
- ; copy <physical plane width bytes>
- LODSB
- OR AL,AL
- JZ SHORT @@Transparent
- MOV [ES:DI],AL
- @@Transparent:
- INC DI
- @@Do_Wrapped_Side:
- MOV AL,[Wrap_Flag] ; any wrapping ?
- OR AL,AL
- JZ SHORT @@Finished_Row ; no - forget it
- SUB DI,DX
-
- ;
- ; Blit the part of the sprite that has been wrapped (if neccessary)
- ;
- MOV CX,[Wrapped_Width]
- SHR CX,1
- JZ SHORT @@WWords_Done
-
- ALIGN 4
- @@WNext_Word:
- LODSW
- OR AX,AX
- JZ SHORT @@WTransparent_Word
- OR AL,AL
- JZ SHORT @@WTransparent0
- MOV [ES:DI],AL
- @@WTransparent0:
- OR AH,AH
- JZ SHORT @@WTransparent1
- MOV [ES:DI+1],AH
- @@WTransparent1:
- @@WTransparent_Word:
- ADD DI,BX
- LOOP SHORT @@WNext_Word
- @@WWords_Done:
- MOV CX,[Wrapped_Width]
- RCR CX,1
- JNC SHORT @@Finished_Row
- ; copy <wrapped length width bytes>
- LODSB
- OR AL,AL
- JZ SHORT @@WTransparent
- MOV [ES:DI],AL
- @@WTransparent:
-
- @@Finished_Row:
- ; next row
- ; bump sauce
- POP SI
- ADD SI,[Plane_Width]
- ; bump destination
- POP DI
- ADD DI,DX
- POP CX
- LOOP @@Next_Row
- @@Plane_Clipped_Out:
- ; next plane
- ; bump sauce
- MOV AX,[Plane_Size]
- ADD [Source_Start],AX
- ; reset destination
- ; bump plane
- INC [Plane_Number] ; bump onto next physical
- AND [Plane_Number],3 ; plane
- JNZ SHORT @@No_Physical_Plane_Adjust
- INC [Destination_Start]
- @@No_Physical_Plane_Adjust:
- POP CX ; get plane count
- MOV AX,[X_Pixel] ; X pixel
- INC AX
- CMP AX,VGA_X_Resolution
- JL SHORT @@No_Wrap_Check ; finish if off screen
- XOR BL,BL
- MOV [Wrap_Flag],BL ; turn off wrapping
- MOV BX,320/4 ; if whole plane is wrapped
- SUB [Destination_Start],BX ; and bump up a screen line
- XOR AX,AX
- @@No_Wrap_Check:
- MOV [X_Pixel],AX
- DEC CX
- JNZ NEAR @@Next_Plane
- @@Done_Last_Pixel:
-
- POP DS ; restore registers
- POPAD
-
- LEAVE
-
- RET
- @@Map_Mask_Lookup:
- db 01
- db 02
- db 04
- db 08
- ENDP Display_Wrapped_Sprite
-
-
- ;----------------------------------------------------------------------------:
- ; Transfer image data of sprites current frame to screen :
- ; Sprite colour 0 is *not* treated as transparent :
- ; Enter with EAX as sprite number to display :
- ;----------------------------------------------------------------------------:
-
- ; you don't actually need this, but ....
- ; i thought t'would be handy!
-
- PROC Display_Unclipped_Block NEAR
- LOCAL Plane_Size:WORD,Plane_Number:WORD,Physical_Plane_Width:WORD
- LOCAL Plane_Width:WORD,Bytes_In_Plane:WORD,Image_Width:WORD
- LOCAL Image_Height:WORD,Destination_Start:WORD
- LOCAL Source_Start:WORD =Local_Length
-
- ENTER Local_Length,0
-
- PUSHAD ; save registers
- PUSH DS
-
- ASSUME DS:Data_Segment
-
- MOV DX,Video_Segment
- MOV ES,DX ; ES points to VGA's segment
- ASSUME ES:Video_Segment
-
- ERRIF (Sprite_Item_Size NE 20h) ; form address of sprite in SI
- MOV SI,AX
- SHL SI,5
- ADD SI,OFFSET Sprite_List
- ; form video destination addr
- MOV BX,[(Sprite_Item PTR SI).Current_X]
- MOV CX,[(Sprite_Item PTR SI).Current_Y]
- Compute_Video_Address
- MOV [Destination_Start],DI
- ; get first plane of sprite
- MOV [Plane_Number],AX
- ; form frame address in DI
- MOV DI,[(Sprite_Item PTR SI).Current_Frame]
- SHL DI,4
- ADD DI,OFFSET Frame_List
- MOV AX,[(Frame_Item PTR DI).Image_Plane_Size]
- MOV [Plane_Size],AX
- ; get sprite dimensions etc.
- MOV BX,[(Frame_Item PTR DI).Image_X_Size]
- MOV [Image_Width],BX
- MOV AX,BX
- AND AX,NOT 3
- CMP AX,BX
- JZ SHORT @@No_Plane_Adjust
- ADD AX,4
- @@No_Plane_Adjust:
- SHR AX,2
- MOV [Plane_Width],AX
- MOV CX,[(Frame_Item PTR DI).Image_Y_Size]
- MOV [Image_Height],CX
- ; get address of sprite image
- MOV ESI,[(Frame_Item PTR DI).Image_Data]
- MOV [Source_Start],SI ; SI is smallest possible offset
-
- SHR ESI,16 ; high word of ESI is segment
- MOV AX,SI
- MOV DS,AX ; in DS:SI (sauce)
- ASSUME DS:NOTHING ; where?
- MOV CX,4 ; four planes
- @@Next_Plane:
- PUSH CX
- ; for each plane
- ; set write plane
- MOV SI,[Plane_Number] ; convert plane # to mask
- MOV AH,[BYTE CS:@@Map_Mask_Lookup+SI]
- MOV AL,Map_Mask
- MOV DX,Sequencer_Address_Port
- OUT DX,AX ; send to hardware
- ; work out physical plane width
- MOV BX,[Image_Width]
- ADD BX,CX ; cx is plane count
- DEC BX
- SHR BX,2 ; bx is now plane width
- MOV [Physical_Plane_Width],BX
- MOVZX ECX,[Image_Height]
- MOV SI,[Source_Start]
- MOV DI,[Destination_Start]
- MOV DX,320/4 ; screen row length
- SUB DX,[Physical_Plane_Width]
-
- ALIGN 4
- @@Next_Row:
- ; for each row
- PUSH BX
- PUSH CX
- PUSH SI
-
-
- MOV CX,BX ; bx == [Physical_Plane_Width]
- ; copy <physical plane width bytes>
-
- TEST DI,3
- JZ SHORT @@Dword_Aligned
- MOV CX,DI
- AND CX,3
- SUB BX,CX
- @@Align_Data:
- LODSB
- OR AL,AL
- JZ SHORT @@Lead_Transparent
- MOV [ES:DI],AL
- @@Lead_Transparent:
- INC DI
- LOOP SHORT @@Align_Data
-
- @@Dword_Aligned:
-
- MOVZX ECX,BX
- SHR ECX,2
- REP MOVSD
- MOV CX,BX ; bx == [Physical_Plane_Width]
- AND CX,3
- REP MOVSB
- ; next row
- ; bump sauce
- POP SI
- ADD SI,[Plane_Width]
- ; bump destination
- ADD DI,DX ; DX == 320/4
- POP CX
- POP BX
- LOOP SHORT @@Next_Row
- ; next plane
- ; bump sauce
- MOV AX,[Plane_Size]
- ADD [Source_Start],AX
- ; reset destination
- ; bump plane
- INC [Plane_Number]
- AND [Plane_Number],3
- JNZ SHORT @@No_Physical_Plane_Adjust
- INC [Destination_Start]
- @@No_Physical_Plane_Adjust:
- POP CX
- LOOP SHORT @@Next_Plane
-
- POP DS ; restore registers
- POPAD
-
- LEAVE
-
- RET
- @@Map_Mask_Lookup:
- db 01
- db 02
- db 04
- db 08
- ENDP Display_Unclipped_Block
-
- ;----------------------------------------------------------------------------:
- ; Limit Sprite : Limits sprite to screen borders :
- ; Enter with EAX as sprite number :
- ;----------------------------------------------------------------------------:
-
- PROC Limit_Sprite NEAR
- PUSHA
- ASSUME DS:Data_Segment
- SHL AX,5 ; from sprite address
- MOV SI,AX
- ADD SI,OFFSET Sprite_List
- MOV DI,[(Sprite_Item PTR SI).Current_Frame]
- SHL DI,4 ; form frame address
- ADD DI,OFFSET Frame_List
- ; from right bottom sprite
- ; co-ordinate
- MOV BX,[(Frame_Item PTR DI).Image_X_Size]
- MOV CX,[(Frame_Item PTR DI).Image_Y_Size]
- ADD BX,[(Sprite_Item PTR SI).Current_X]
- ADD CX,[(Sprite_Item PTR SI).Current_Y]
- CMP BX,VGA_X_Resolution
- JBE SHORT @@No_X_Clip
- MOV BX,VGA_X_Resolution ; form clipped x
- SUB BX,[(Frame_Item PTR DI).Image_X_Size]
- MOV [(Sprite_Item PTR SI).Current_X],BX
- @@No_X_Clip:
- CMP CX,VGA_Y_Resolution
- JBE SHORT @@No_Y_Clip
- MOV CX,VGA_Y_Resolution ; form clipped y
- SUB CX,[(Frame_Item PTR DI).Image_Y_Size]
- MOV [(Sprite_Item PTR SI).Current_Y],CX
- @@No_Y_Clip:
- POPA
- RET
- ENDP Limit_Sprite
-
- ENDS Code_Segment
-
-
- END